//
//  UIImage+QRCode.m
//  QRCode_Demo
//
//  Created by 沈红榜 on 15/11/17.
//  Copyright © 2015年 沈红榜. All rights reserved.
//

#import "UIImage+TKIMQRCode.h"
#import <AVFoundation/AVFoundation.h>

@implementation UIImage (TKIMQRCode)

void ProviderReleaseData (void *info, const void *data, size_t size)
{
    free((void*)data);
}


/**
 *  @Author lpm, 15-12-08 10:12:17
 *
 *  @brief   生成一张二维码
 *
 *  @param content 内容
 *  @param size 大小
 *
 *  @return
 */
+ (UIImage *)qrImageWithContent:(NSString *)content size:(CGFloat)size
{
    CIImage *image = [UIImage qrByContent:content];
    CGRect extent = CGRectIntegral(image.extent);
    CGFloat scale = MIN(size/CGRectGetWidth(extent), size/CGRectGetHeight(extent));
    // 创建bitmap;
    size_t width = CGRectGetWidth(extent) * scale;
    size_t height = CGRectGetHeight(extent) * scale;
    CGColorSpaceRef cs = CGColorSpaceCreateDeviceGray();
    CGContextRef bitmapRef = CGBitmapContextCreate(nil, width, height, 8, 0, cs, (CGBitmapInfo)kCGImageAlphaNone);
    CIContext *context = [CIContext contextWithOptions:nil];
    CGImageRef bitmapImage = [context createCGImage:image fromRect:extent];
    CGContextSetInterpolationQuality(bitmapRef, kCGInterpolationNone);
    CGContextScaleCTM(bitmapRef, scale, scale);
    CGContextDrawImage(bitmapRef, extent, bitmapImage);
    // 保存bitmap到图片
    CGImageRef scaledImage = CGBitmapContextCreateImage(bitmapRef);
    CGContextRelease(bitmapRef);
    CGImageRelease(bitmapImage);
    return [UIImage imageWithCGImage:scaledImage];
}


/**
 *  @Author lpm, 15-12-08 10:12:10
 *
 *  @brief 生成一张二维码
 *
 *  @param content 内容
 *  @param size    大小
 *  @param red
 *  @param green
 *  @param blue
 *
 *  @return
 */
+ (UIImage *)qrImageWithContent:(NSString *)content size:(CGFloat)size red:(NSInteger)red green:(NSInteger)green blue:(NSInteger)blue
{
    UIImage *image = [UIImage qrImageWithContent:content size:size];
    const int imageWidth = image.size.width;
    const int imageHeight = image.size.height;
    size_t      bytesPerRow = imageWidth * 4;
    uint32_t* rgbImageBuf = (uint32_t*)malloc(bytesPerRow * imageHeight);
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(rgbImageBuf, imageWidth, imageHeight, 8, bytesPerRow, colorSpace,
                                                 kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipLast);
    
    CGContextDrawImage(context, CGRectMake(0, 0, imageWidth, imageHeight), image.CGImage);
    // 遍历像素
    int pixelNum = imageWidth * imageHeight;
    uint32_t* pCurPtr = rgbImageBuf;
    
    for (int i = 0; i < pixelNum; i++, pCurPtr++)
    {
        if ((*pCurPtr & 0xFFFFFF00) < 0x99999900)    // 将白色变成透明
        {
            // 改成下面的代码，会将图片转成想要的颜色
            uint8_t* ptr = (uint8_t*)pCurPtr;
            ptr[3] = red; //0~255
            ptr[2] = green;
            ptr[1] = blue;
        }
        else
        {
            uint8_t* ptr = (uint8_t*)pCurPtr;
            ptr[0] = 0;
        }
    }
    // 输出图片
    CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, rgbImageBuf, bytesPerRow * imageHeight, ProviderReleaseData);
    CGImageRef imageRef = CGImageCreate(imageWidth, imageHeight, 8, 32, bytesPerRow, colorSpace,
                                        kCGImageAlphaLast | kCGBitmapByteOrder32Little, dataProvider,
                                        NULL, true, kCGRenderingIntentDefault);
    CGDataProviderRelease(dataProvider);
    UIImage* resultUIImage = [UIImage imageWithCGImage:imageRef];
    // 清理空间
    CGImageRelease(imageRef);
    CGContextRelease(context);
    CGColorSpaceRelease(colorSpace);
        
    return resultUIImage;
}


/**
 *  @Author lpm, 15-12-08 10:12:36
 *
 *  @brief  生成一张二维码
 *
 *  @param content 内容
 *  @param logo    logo
 *  @param size    大小
 *  @param red
 *  @param green
 *  @param blue
 *
 *  @return
 */
+ (UIImage *)qrImageWithContent:(NSString *)content logo:(UIImage *)logo size:(CGFloat)size red:(NSInteger)red green:(NSInteger)green blue:(NSInteger)blue
{
    UIImage* resultUIImage = [self qrImageWithContent:content size:size red:red green:green blue:blue];
    // 添加logo
    CGFloat logoW = resultUIImage.size.width / 5.;
    CGRect logoFrame = CGRectMake(logoW * 2, logoW * 2, logoW, logoW);
    UIGraphicsBeginImageContext(resultUIImage.size);
    [resultUIImage drawInRect:CGRectMake(0, 0, resultUIImage.size.width, resultUIImage.size.height)];
    [logo drawInRect:logoFrame];
    UIImage *kk = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return kk;
}


/**
 *  @Author lpm, 15-12-08 10:12:46
 *
 *  @brief  生成一张二维码
 *
 *  @param content  二维码内容
 *
 *  @return
 */

+ (UIImage *)qrImageByContent:(NSString *)content
{
    //输出二维码
    CIImage *qrImage = [self qrByContent:content];
    
    //默认大小300*300
    CGSize size = CGSizeMake(300, 300);
    
    //生成图片
    CGImageRef cgImage = [[CIContext contextWithOptions:nil] createCGImage:qrImage fromRect:qrImage.extent];
    UIGraphicsBeginImageContext(size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetInterpolationQuality(context, kCGInterpolationNone);
    CGContextScaleCTM(context, 1, -1);
    CGContextDrawImage(context, CGContextGetClipBoundingBox(context), cgImage);
    UIImage *codeImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    CGImageRelease(cgImage);
    
    return codeImage;
}


#pragma mark  私有方法


/**
 *  @Author lpm, 15-12-08 10:12:55
 *
 *  @brief  生成二维码
 
        qrcode有个纠错等级的设置

        There are 4 error correction levels used for QR codes, with each one adding different amounts of “backup” data depending on how much damage the QR code is expected to suffer in its intended environment, and hence how much error correction may be required:

        Level L – up to 7% damage
        Level M – up to 15% damage
        Level Q – up to 25% damage
        Level H – up to 30% damage
        UIColor *onColor = [UIColor blackColor];
        UIColor *offColor = [UIColor whiteColor];

        CIFilter *colorFilter = [CIFilter filterWithName:@"CIFalseColor"
        keysAndValues:
        @"inputImage", qrFilter.outputImage,
        @"inputColor0", [CIColor colorWithCGColor:onColor.CGColor],
        @"inputColor1", [CIColor colorWithCGColor:offColor.CGColor],
        nil];

        CIImage *qrImage = colorFilter.outputImage;
 *
 *  @param content
 *
 *  @return
 */
+ (CIImage *)qrByContent:(NSString *)content
{
    //将字符串UTF-8编码
    NSData *stringData = [content dataUsingEncoding:NSUTF8StringEncoding];
    
    //初始化二维码生成器
    CIFilter *qrFilter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
    [qrFilter setValue:stringData forKey:@"inputMessage"];
    [qrFilter setValue:@"M" forKey:@"inputCorrectionLevel"];
    
    //输出二维码
    CIImage *qrImage = qrFilter.outputImage;
    return qrImage;
}

@end
